/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author subx
 */
public class ConfigReader {
    private File file;
    private FileReader reader;
    private BufferedReader buffer;

    private Config config;
    private List<String> commands;


    /**
     * Construtor que recebe como parâmetro o arquivo de configuração contendo
     * a instância que será analisada.
     *
     * @param file Arquivo contendo configuração.
     * @throws FileNotFoundException
     */
    public ConfigReader(File file) throws FileNotFoundException {
        this.file = file;
        reader = new FileReader(file);
        buffer = new BufferedReader(reader);
        commands = new LinkedList<String>();

        initCommands();

        //Inicializa Config
        config = Config.getInstance();
        //config.setInfo(commands);
    }

    public void initCommands(){
        commands.add(0, "NAME");
        commands.add(1, "AUTHOR");
        commands.add(2, "CITY");
        commands.add(3, "STATE");
        commands.add(4, "LOCATION");
    }

    public File getFile() {
        return this.file;
    }

    /**
     * Lê o arquivo de configuração carregado para a memória, extraindo informações
     * da instância para um objeto do tipo Config.
     * 
     * @throws IOException
     */
    public void ReadConfigFile() throws IOException {
        int cmd;
        String line = null;

        while((line = buffer.readLine()) != null){
            if(line.isEmpty() || isComment(line.charAt(0))){
                continue;
            }else if((cmd = hasCommand(line)) != -1){
                readCommand(line, cmd);
            }else{
                readNode(line);
            }
        }

        //Atualiza as arestas do grafo.
        config.getGraph().Update();

        closeAll();
    }

    private void readNode(String line) throws IOException {
        int id;
        char c0;
        
        c0 = line.charAt(0);
        id = Character.digit(c0, 10);

        readNodeInfo(id, line);

        while((line = buffer.readLine()) != null){
            if(line.isEmpty())
                break;

            readNodeEdge(id, line);
        }
    }

    private void readCommand(String line, int cmd) {
        String tmp = null;
        
        tmp = line.substring(commands.get(cmd).length() + 2);
        config.setInfo(cmd, tmp);
    }

    public void closeAll() throws IOException{
        reader.close();
        buffer.close();
    }

    private boolean isComment(char s){
        return s == '#';
    }

    private int hasCommand(String s){
        int cmd = -1;
        
        for(String e : commands){
            if(s.contains(e)){
                cmd++;
                return cmd;
            }else{
                cmd++;
            }
        }

        cmd = -1;
        return cmd;
    }

    public Config getConfig() {
        return config;
    }

    /**
     * Analisa a string s retirando informções como poisção(x,y) e peso sobre o
     * nó de ID id.
     *
     * @param id ID do nó.
     * @param s String correspondente a linha do arquivo de configuração.
     */
    private void readNodeInfo(int id, String s){
        Integer x, y;
        Integer weight;
        String[] values;
        
        values = s.split(" ");
        
        x = new Integer(values[1]);
        y = new Integer(values[2]);
        weight = new Integer(values[3]);

        //System.out.println("X: " + x + "\tY: " + y + "\tWeight: " + weight);

        config.setNode(id, weight, y, x);
    }

    private void readNodeEdge(int id, String s){
        Integer ide;
        Integer weight;
        String[] values;

        values = s.split(" ");

        ide = new Integer(values[1]);
        weight = new Integer(values[2]);

        config.setEdge(id, ide, weight);
    }
}
